package com.tianji.learning.service.impl;

import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tianji.api.client.remark.RemarkClient;
import com.tianji.api.client.user.UserClient;
import com.tianji.api.dto.remark.LikedTimesDTO;
import com.tianji.api.dto.user.UserDTO;
import com.tianji.common.autoconfigure.mq.RabbitMqHelper;
import com.tianji.common.constants.MqConstants;
import com.tianji.common.domain.dto.PageDTO;
import com.tianji.common.exceptions.BadRequestException;
import com.tianji.common.exceptions.DbException;
import com.tianji.common.utils.BeanUtils;
import com.tianji.common.utils.ObjectUtils;
import com.tianji.common.utils.UserContext;
import com.tianji.learning.domain.dto.ReplyDTO;
import com.tianji.learning.domain.enums.PointsRecordType;
import com.tianji.learning.domain.enums.QuestionStatus;
import com.tianji.learning.domain.po.InteractionQuestion;
import com.tianji.learning.domain.po.InteractionReply;
import com.tianji.learning.domain.po.PointsRecord;
import com.tianji.learning.domain.query.ReplyPageQuery;
import com.tianji.learning.domain.vo.ReplyVO;
import com.tianji.learning.mapper.InteractionQuestionMapper;
import com.tianji.learning.mapper.InteractionReplyMapper;
import com.tianji.learning.service.IInteractionReplyService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import static com.tianji.common.constants.Constant.DATA_FIELD_NAME_CREATE_TIME;
import static com.tianji.common.constants.Constant.DATA_FIELD_NAME_LIKED_TIME;
import static com.tianji.common.constants.MqConstants.Exchange.POINT_RECORD_EXCHANGE;

/**
 * <p>
 * 互动问题的回答或评论 服务实现类
 * </p>
 *
 * @author author
 * @since 2025-03-26
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class InteractionReplyServiceImpl extends ServiceImpl<InteractionReplyMapper, InteractionReply> implements IInteractionReplyService
{
    // 构造函数注入
    private final UserClient userClient;

    // 评论服务的远程调用
    private final RemarkClient remarkClient;

    // 注入Mapper
    private final InteractionQuestionMapper interactionQuestionMapper;

    private final RabbitMqHelper rabbitMqHelper;
    // 新增回复涉及到多表写操作，必须要加事务，还好这里不需要加分布式事务
    @Override
    @Transactional
    public void addReply(ReplyDTO replyDTO) {
        InteractionReply interactionReply = BeanUtils.copyBean(replyDTO, InteractionReply.class);
        interactionReply.setUserId(UserContext.getUser());

        // 回复表中新增回复
        boolean result = this.save(interactionReply);
        if (!result) {
            log.error("新增回复失败");
            return;
        }

        // 新增回复成功后，需要将对应的questionId和replyId对应的answer_times和reply_times加一（如果有的话），这里一定要从一开始就维护好
        // 三级回复字段，有 target_replyId 就一定有 answer_id, 有 answer_id 就一定有 question_id
        Long questionId = replyDTO.getQuestionId();
        Long answerId = replyDTO.getAnswerId();
        Long targetReplyId = replyDTO.getTargetReplyId();
        if ( questionId != null && questionId != 0 ) {
            InteractionQuestion interactionQuestion = interactionQuestionMapper.selectById(questionId);
            //  更新回复次数和最新回复id
            interactionQuestion.setAnswerTimes(interactionQuestion.getAnswerTimes() + 1);
            interactionQuestion.setLatestAnswerId(interactionReply.getId());
            interactionQuestionMapper.updateById(interactionQuestion);

            if (answerId == null || answerId == 0) {
                PointsRecord pointsRecord = new PointsRecord();
                pointsRecord.setPoints(3);
                pointsRecord.setUserId(UserContext.getUser());
                pointsRecord.setType(PointsRecordType.QA);
                // 说明是直接回答的问题，当前用户积分+3
                rabbitMqHelper.sendAsyn(POINT_RECORD_EXCHANGE, "points.reply.change", pointsRecord);
            }
        }

        if (answerId != null && answerId != 0) {
            InteractionReply ir = this.getById(answerId);
            ir.setReplyTimes(ir.getReplyTimes() + 1);
            this.updateById(ir);
        }

        if (targetReplyId != null && targetReplyId != 0 ) {
            if (!targetReplyId.equals(answerId)) {
                InteractionReply ir = this.getById(targetReplyId);
                ir.setReplyTimes(ir.getReplyTimes() + 1);
                this.updateById(ir);
            }
        }

    }

    @Override
    public PageDTO<ReplyVO> getPage(ReplyPageQuery replyPageQuery, Boolean isStudent) {
        // 问题id和回答id至少要有一个
        if (replyPageQuery.getQuestionId() == null && replyPageQuery.getAnswerId() == null) {
            throw new BadRequestException("问题id和回答id至少要有一个");
        }

        // 要么根据问题查询回答，要么根据回答查询评论
        boolean isQueryQuestion = replyPageQuery.getQuestionId() != null;

        // 分页查询互动回复列表
        Page<InteractionReply> page = this.lambdaQuery()
                .eq(replyPageQuery.getQuestionId() != null, InteractionReply::getQuestionId, replyPageQuery.getQuestionId())
                .eq(replyPageQuery.getAnswerId() != null, InteractionReply::getAnswerId, replyPageQuery.getAnswerId())
                .and(isQueryQuestion, wrapper -> wrapper
                        .eq(InteractionReply::getAnswerId, 0)
                        .or()
                        .isNull(InteractionReply::getAnswerId)
                )
                .eq(InteractionReply::getHidden, false)
                .page(replyPageQuery.toMpPage(
                        new OrderItem(DATA_FIELD_NAME_LIKED_TIME, false),
                        new OrderItem(DATA_FIELD_NAME_CREATE_TIME, false)
                ));
        List<InteractionReply> records = page.getRecords();

        List<ReplyVO> recordss = new ArrayList<>(records.size());

        // 封装提问者信息和回复目标信息
        // 3.3 查询用户
        Set<Long> ids = records.stream().filter(v->!v.getAnonymity()).map(v->v.getUserId()).collect(Collectors.toSet());
        Set<Long> targetIds = records.stream().map(v->v.getTargetUserId()).filter(targetUserId->targetUserId != null && targetUserId != 0L).collect(Collectors.toSet());

        ids.addAll(targetIds);
        List<UserDTO> userDTOList = userClient.queryUserByIds(ids);
        // 生成用户的userMap
        Map<Long, UserDTO> userMp = userDTOList.stream().collect(Collectors.toMap(UserDTO::getId, Function.identity()));

        // 3.4、查询目标评论是否匿名
        List<Long> targetReplyIds = records.stream().filter(v->v.getTargetReplyId() != null && v.getTargetReplyId() != 0L).map(v->v.getTargetReplyId()).collect(Collectors.toList());
        Map<Long, Boolean> targetReplyAnonymityMap = new HashMap<>(targetReplyIds.size());
        // 创建目标回复匿名信息
        if (ObjectUtils.isNotEmpty(targetReplyIds)) {
            List<InteractionReply> replies = this.listByIds(targetReplyIds);
            targetReplyAnonymityMap =
                    replies.stream().collect(Collectors.toMap(InteractionReply::getId, InteractionReply::getAnonymity));
        }


        List<Long> bizIds = records.stream().map(v->v.getId()).collect(Collectors.toList());

        // 查询当前用户对所有评论的点赞情况，如果点过，按钮置灰
        Map<Long, Boolean> likeMp = remarkClient.isLiked(bizIds);

        // 循环遍历封装
        for (InteractionReply record : records) {
            ReplyVO replyVO = BeanUtils.copyBean(record, ReplyVO.class);
            UserDTO userDTO = userMp.get(record.getUserId());
            if (ObjectUtils.isNotEmpty(userDTO)) {
                if (!record.getAnonymity()) {
                    replyVO.setUserName(userDTO.getUsername());
                    replyVO.setUserIcon(userDTO.getIcon());
                } else {
                    replyVO.setUserName(null);
                    replyVO.setUserIcon(null);
                }

                replyVO.setUserType(userDTO.getType());
            }

            if (ObjectUtils.isNotNull(record.getTargetUserId())) {
                UserDTO userDTO1 = userMp.get(record.getTargetUserId());
                if (ObjectUtils.isNotEmpty(userDTO1)) {
                    replyVO.setTargetUserName(userDTO1.getUsername());
                }
            }

            if (record.getTargetReplyId() != null && ObjectUtils.isNotEmpty(targetReplyAnonymityMap)) {
                if (targetReplyAnonymityMap.getOrDefault(record.getTargetReplyId(), false)) {
                    replyVO.setTargetUserName(null);
                } else {
                    UserDTO tmp = userMp.get(record.getTargetUserId());
                    if (ObjectUtils.isNotNull(tmp)) {
                        String userName = tmp.getUsername();
                        if (ObjectUtils.isNotEmpty(userName)) {
                            replyVO.setTargetUserName(userName);
                        }
                    }
                }
            }
            replyVO.setLiked(likeMp.getOrDefault(record.getId(), false));
            recordss.add(replyVO);
        }

        if (isQueryQuestion && !isStudent) {
            // 根据问题id查询互动回复列表
            // 3.1、查询问题
            InteractionQuestion question = new InteractionQuestion();
            question.setId(replyPageQuery.getQuestionId());
            question.setStatus(QuestionStatus.CHECKED);
            interactionQuestionMapper.updateById(question);
        }

        return PageDTO.of(page, recordss);
    }

    /**
     * 隐藏回复
     *
     * @param id
     */
    @Override
    public void hideAll(Long id) {
        // 查询隐藏的这个评论是否是某个问题的最新回答id，如果是，需要批量更新这些问题Id的所有最新回答id
        // for循环中更新所有问题的最新回答id，每次都需要根据相应的问题id对回复进行排序并过滤隐藏的评论,按创建时间排序取最上面一条
//        InteractionReply one = this.lambdaQuery()
//                .eq(InteractionReply::getQuestionId, record.getId())
//                .eq(InteractionReply::getHidden, false)
//                .last("limit 1")
//                .orderByDesc(InteractionReply::getCreateTime)
//                .one();
//        one.getUserId();
//        one.getContent();
    }

    /**
     * 显示回复
     *
     * @param id
     */
    @Override
    public void displayAll(Long id) {

    }

    /**
     * 根据回答查评论
     *
     * @param replyPageQuery
     */
    @Override
    public PageDTO<ReplyVO> pageQuery(ReplyPageQuery replyPageQuery) {
        return null;
    }
}
